package com.huawei.zyb.taskManager.infrastructure.persistence.repository;

import com.huawei.zyb.taskManager.domain.requirement.entity.ReferenceDocument;
import com.huawei.zyb.taskManager.domain.requirement.repository.ReferenceDocumentRepository;
import com.huawei.zyb.taskManager.domain.requirement.valueobject.DocumentType;
import com.huawei.zyb.taskManager.domain.requirement.valueobject.ReferenceDocumentId;
import com.huawei.zyb.taskManager.domain.requirement.valueobject.RequirementId;
import com.huawei.zyb.taskManager.infrastructure.persistence.mapper.ReferenceDocumentMapper;
import com.huawei.zyb.taskManager.infrastructure.persistence.mapper.ReferenceDocumentDomainMapper;
import com.huawei.zyb.taskManager.infrastructure.persistence.po.ReferenceDocumentPO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 参考文档仓储实现
 */
@Repository
public class ReferenceDocumentRepositoryImpl implements ReferenceDocumentRepository {
    
    @Autowired
    private ReferenceDocumentMapper referenceDocumentMapper;
    
    @Override
    public ReferenceDocument save(ReferenceDocument document) {
        ReferenceDocumentPO documentPO = ReferenceDocumentDomainMapper.toReferenceDocumentPO(document);
        
        // 检查是否已存在
        ReferenceDocumentPO existingPO = referenceDocumentMapper.findByDocumentId(documentPO.getDocumentId());
        if (existingPO == null) {
            referenceDocumentMapper.insert(documentPO);
        } else {
            documentPO.setId(existingPO.getId());
            referenceDocumentMapper.update(documentPO);
        }
        
        return document;
    }
    
    @Override
    public Optional<ReferenceDocument> findById(ReferenceDocumentId documentId) {
        ReferenceDocumentPO documentPO = referenceDocumentMapper.findByDocumentId(documentId.getValue());
        return documentPO != null ? 
            Optional.of(ReferenceDocumentDomainMapper.toReferenceDocument(documentPO)) : 
            Optional.empty();
    }
    
    @Override
    public List<ReferenceDocument> findByRequirementId(RequirementId requirementId) {
        List<ReferenceDocumentPO> documentPOs = referenceDocumentMapper.findByRequirementId(requirementId.getValue());
        return documentPOs.stream()
            .map(ReferenceDocumentDomainMapper::toReferenceDocument)
            .collect(Collectors.toList());
    }
    
    @Override
    public List<ReferenceDocument> findByRequirementIdAndType(RequirementId requirementId, DocumentType type) {
        List<ReferenceDocumentPO> documentPOs = referenceDocumentMapper.findByRequirementIdAndType(
            requirementId.getValue(), type.getCode());
        return documentPOs.stream()
            .map(ReferenceDocumentDomainMapper::toReferenceDocument)
            .collect(Collectors.toList());
    }
    
    @Override
    public long countByRequirementId(RequirementId requirementId) {
        return referenceDocumentMapper.countByRequirementId(requirementId.getValue());
    }
    
    @Override
    public long countByRequirementIdAndType(RequirementId requirementId, DocumentType type) {
        return referenceDocumentMapper.countByRequirementIdAndType(
            requirementId.getValue(), type.getCode());
    }
    
    @Override
    public List<ReferenceDocument> findRecentlyViewedByRequirementId(RequirementId requirementId, int limit) {
        List<ReferenceDocumentPO> documentPOs = referenceDocumentMapper.findRecentlyViewedByRequirementId(
            requirementId.getValue(), limit);
        return documentPOs.stream()
            .map(ReferenceDocumentDomainMapper::toReferenceDocument)
            .collect(Collectors.toList());
    }
    
    @Override
    public List<ReferenceDocument> findMostViewedByRequirementId(RequirementId requirementId, int limit) {
        List<ReferenceDocumentPO> documentPOs = referenceDocumentMapper.findMostViewedByRequirementId(
            requirementId.getValue(), limit);
        return documentPOs.stream()
            .map(ReferenceDocumentDomainMapper::toReferenceDocument)
            .collect(Collectors.toList());
    }
    
    @Override
    public void deleteById(ReferenceDocumentId documentId) {
        referenceDocumentMapper.deleteByDocumentId(documentId.getValue());
    }
    
    @Override
    public void deleteByRequirementId(RequirementId requirementId) {
        referenceDocumentMapper.deleteByRequirementId(requirementId.getValue());
    }
    
    @Override
    public boolean existsById(ReferenceDocumentId documentId) {
        return referenceDocumentMapper.existsByDocumentId(documentId.getValue()) > 0;
    }
    
    @Override
    public boolean existsByRequirementIdAndUrl(RequirementId requirementId, String url) {
        return referenceDocumentMapper.existsByRequirementIdAndUrl(
            requirementId.getValue(), url) > 0;
    }
    
    @Override
    public List<ReferenceDocument> findAll() {
        List<ReferenceDocumentPO> documentPOs = referenceDocumentMapper.findAll();
        return documentPOs.stream()
            .map(ReferenceDocumentDomainMapper::toReferenceDocument)
            .collect(Collectors.toList());
    }
    
    @Override
    public List<ReferenceDocument> findByType(DocumentType type) {
        List<ReferenceDocumentPO> documentPOs = referenceDocumentMapper.findByType(type.getCode());
        return documentPOs.stream()
            .map(ReferenceDocumentDomainMapper::toReferenceDocument)
            .collect(Collectors.toList());
    }
    
    @Override
    public List<ReferenceDocument> findByUploader(String uploader) {
        List<ReferenceDocumentPO> documentPOs = referenceDocumentMapper.findByUploader(uploader);
        return documentPOs.stream()
            .map(ReferenceDocumentDomainMapper::toReferenceDocument)
            .collect(Collectors.toList());
    }
    
    @Override
    public List<ReferenceDocument> findRecentDocuments(int limit) {
        List<ReferenceDocumentPO> documentPOs = referenceDocumentMapper.findRecentDocuments(limit);
        return documentPOs.stream()
            .map(ReferenceDocumentDomainMapper::toReferenceDocument)
            .collect(Collectors.toList());
    }
    
    @Override
    public void delete(ReferenceDocument document) {
        referenceDocumentMapper.deleteByDocumentId(document.getId().getValue());
    }
}